package com.ruolin.micro.gateway.server.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import com.ruolin.micro.gateway.server.cache.MethodRouteMetadataCache;
import com.ruolin.micro.gateway.server.constant.DubboMetadataConstant;
import com.ruolin.micro.gateway.server.constant.PropertiesConstant;
import com.ruolin.micro.gateway.server.metadata.ApplicationRouteMetadata;
import com.ruolin.micro.gateway.server.metadata.InstanceMetadata;
import com.ruolin.micro.gateway.server.metadata.MethodRouteMetadata;
import com.ruolin.micro.gateway.server.metadata.Type;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.rpc.service.GenericService;
import org.springframework.core.env.Environment;

public class GatewayUtils {
    private GatewayUtils(){
        throw new AssertionError("No com.ruolin.micro.gateway.server.utils.GatewayUtils instances for you!");
    }


    public static ReferenceBean<GenericService> buildReferenceBean(InstanceMetadata parameter) {
        ReferenceBean<GenericService> referenceBean = new ReferenceBean<>();

        referenceBean.setGroup(parameter.getGroup());
        referenceBean.setVersion(parameter.getVersion());
        referenceBean.setGeneric(parameter.getGeneric());
        referenceBean.setApplication(new ApplicationConfig(parameter.getApplication()));
        referenceBean.setRegistry(new RegistryConfig(parameter.getAddress()));
        referenceBean.setInterface(parameter.getInterfaceName());
        referenceBean.setProtocol(parameter.getProtocol());
        referenceBean.setCluster(parameter.getCluster());

        return referenceBean;
    }

    public static ApplicationRouteMetadata buildMetadata(InstanceMetadata parameter, ConfigService configService, Environment environment) {
        ApplicationRouteMetadata metadata = new ApplicationRouteMetadata();
        String dataId = DubboServiceUtils.getDataId(parameter.getInterfaceName(), parameter.getVersion(), parameter.getGroup(), parameter.getApplication());

        try {
            String metadataJson = configService.getConfig(dataId, DubboMetadataConstant.METADATA_GROUP, 5000);
            metadata = JSON.parseObject(metadataJson, ApplicationRouteMetadata.class, Feature.values());
            metadata.setEntityPackage(environment.getProperty(PropertiesConstant.ENTITY_PACKAGE));
            for (MethodRouteMetadata methodRouteMetadata : metadata.getMethods()) {
                String routePart = StringUtils.join(methodRouteMetadata.getName());
                methodRouteMetadata.setRoutePart("/"+ routePart);
                MethodRouteMetadataCache.getMethodMetadataCache().put(routePart, methodRouteMetadata);
                ApplicationRouteMetadata finalMetadata = metadata;
                if (methodRouteMetadata.getParameterTypes().stream().anyMatch(m -> m.startsWith(finalMetadata.getEntityPackage()))) {
                    for (Type type : metadata.getTypes()) {
                        if (type.getType().startsWith(metadata.getEntityPackage())) {
                            for (String key : type.getProperties().keySet()) {
                                methodRouteMetadata.getFieldMap().put(key, null);
                            }
                        }
                    }
                }
            }
        } catch (NacosException e) {
            e.printStackTrace();
        }
        metadata.init();
        return metadata;
    }
}
